package com.example.gateway.util;

import com.example.gateway.constant.CommonConstant;
import com.example.gateway.entity.SysUser;
import com.example.gateway.service.UserService;
import com.fasterxml.jackson.core.filter.TokenFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * @Description: TODO
 * @author: 周天翼
 * @date: 2020年07月26日 11:58
 */
@Component
public class TokenCheckUtils {

    private final static Logger logger = LoggerFactory.getLogger(TokenFilter.class);

    @Autowired
    @Lazy
    private RedisUtil redisUtil;

    @Autowired
    private UserService userService;

    /**
     * 校验token的有效性
     *
     * @param token
     */
    public SysUser checkUserTokenIsEffect(String token) throws Exception{
        // 解密获得username，用于和数据库进行对比
        logger.info("解密token");
        String username = JwtUtil.getUsername(token);
        logger.info("解密token获取的username为:"+username);
        if (username == null) {
            System.out.println("token非法无效!");
            throw new Exception("Invalid Token");
        }
        logger.info("解密结果"+username);
        if(username == "解密失败"){
            throw new Exception("Error Token");
        }
        // 查询用户信息
        logger.info("———校验token是否有效————checkUserTokenIsEffect——————— "+ token);
        SysUser loginUser = userService.getUserByName(username);
        logger.info("获取用户信息"+loginUser.toString());
        if (loginUser == null) {
            logger.info("用户不存在!");
            throw new Exception("No Such User");
        }
        // 判断用户状态
        if (loginUser.getStatus() != 1) {
            logger.info("账号已被锁定,请联系管理员!");
            throw new Exception("Locked User");
        }
        logger.info("校验token是否超时失效 & 或者账号密码是否错误");
        if (!jwtTokenRefresh(token, username, loginUser.getPassword())) {
            logger.info("Token失效，请重新登录!");
            throw new Exception("Invalid Token");
        }

        return loginUser;
    }

    /**
     * JWTToken刷新生命周期 （实现： 用户在线操作不掉线功能）
     * 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样)，缓存有效期设置为Jwt有效时间的2倍
     * 2、当该用户再次请求时，通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证
     * 3、当该用户这次请求jwt生成的token值已经超时，但该token对应cache中的k还是存在，则表示该用户一直在操作只是JWT的token失效了，程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值，该缓存生命周期重新计算
     * 4、当该用户这次请求jwt在生成的token值已经超时，并在cache中不存在对应的k，则表示该用户账户空闲超时，返回用户信息已失效，请重新登录。
     * 注意： 前端请求Header中设置Authorization保持不变，校验有效性以缓存中的token为准。
     *       用户过期时间 = Jwt有效时间 * 2。
     *
     * @param userName
     * @param passWord
     * @return
     */
    private boolean jwtTokenRefresh(String token, String userName, String passWord) {
        logger.info("从redis中获取token");
        String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
        logger.info("从redis中获取token"+cacheToken);
        if (oConvertUtils.isNotEmpty(cacheToken)) {
            // 校验token有效性
            if (!JwtUtil.verify(cacheToken, userName, passWord)) {
                String newAuthorization = JwtUtil.sign(userName, passWord);
                // 设置超时时间
                redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization);
                redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME *2 / 1000);
                logger.info("——————————用户在线操作，更新token保证不掉线—————————jwtTokenRefresh——————— "+ token);
            }
            //update-begin--Author:scott  Date:20191005  for：解决每次请求，都重写redis中 token缓存问题
//			else {
//				// 设置超时时间
//				redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, cacheToken);
//				redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
//			}
            //update-end--Author:scott  Date:20191005   for：解决每次请求，都重写redis中 token缓存问题
            return true;
        }
        return false;
    }



}
